// 获取到了原有的数组原型方法
let oldArrayMethods = Array.prototype; // 获取数组原型上的方法

// 创建一个全新的对象 可以找到数组原型上的方法，而且修改对象时不会影响原数组的原型方法
export let arrayMethods = Object.create(oldArrayMethods); // {}.__proto__

// 7个数组原型方法
let methods = [
  // 这七个方法都可以改变原数组
  "push",
  "pop",
  "shift",
  "unshift",
  "sort",
  "reverse",
  "splice",
];
// 劫持数组方法的目的在于要检测到用户修改数据了 >> 视图要更新

// arrayMethods.map
// 面向切片编程
methods.forEach((method) => {
  // arrMethods.push Arrmethod.map
  // push这个方法的目的是什么
  // 数组要添加一项，数组的push的方法可以实现
  // 视图要更新
  // push(3,4)
  arrayMethods[method] = function (...args) { // [{name: '哈哈哈'}] args = [3,4]
    // 函数劫持 AOP
    // 当用户调用数组方法时 会先执行我自己改造的逻辑 在执行数组默认的逻辑
    const ob = this.__ob__;
    // oldArrayMethods原生数组方法
    // 修改原数据
    // 把原有的数组方法先调用了一下。
    let result = oldArrayMethods[method].apply(this, args); // >> 数据可以更改
    // 通知页面进行更新
    // this.arr.push('23')
    let inserted;
    // push unshift splice 都可以新增属性  （新增的属性可能是一个对象类型）
    // 内部还对数组中引用类型也做了一次劫持  [].push({name:'hm'})
    switch (method) {
      case "push":
      case "unshift":
        inserted = args; // 把push或者unfhift进行的数组成员获取到
        break;
      case "splice": // 也是新增属性  可以修改 可以删除  [].splice(arr,1,'div')
        inserted = args.slice(2);
        break;
      default:
        break;
    }
    inserted && ob.observeArray(inserted);
    // render(); // 重新渲染界面
    return result;
  };
});
